/******************************************************************************
	This file is a part of the Snapshot Bioinformatics Project

	Copyright (C) 2012-2013 Jarom Schow

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#ifndef SNAPSHOT_TREE_H
#define SNAPSHOT_TREE_H

#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QHash>
#include <QtCore/QObject>

#include "SqlServer.h"
#include "Progress.h"

class QTextStream;
class SnapshotGene;
class SnapshotGeneCollection;

class SnapshotNode {
public:
	
	SnapshotNode();
	SnapshotNode( int taxId, const QString &rank, int genCodeId, int mitoGenCodeId );
	virtual ~SnapshotNode();

	SnapshotNode*	getParent() const;

	int				getNumChildren() const;
	int				indexOf( SnapshotNode *child ) const;
	SnapshotNode*	getChild( int which ) const;

	QListIterator<SnapshotNode*>	getChildIterator() const;

	void	addChild( SnapshotNode *child );

	void	setScientificName( const QString &name );
	QString	getScientificName() const;

	void	setCommonName( const QString &name );
	QString	getCommonName() const;

	void	setTaxonId( int id );
	int		getTaxonId() const;

	void	setGeneticCode( int id );
	int		getGeneticCode() const;

	void	setMitoGeneticCode( int id );
	int		getMitoGeneticCode() const;

	void	setRank( const QString &rank );
	QString	getRank() const;

	int		getNumSpecies() const;

	float	getCoverage() const;
	
	int				getNumGenes() const;
	SnapshotGene*	getGene( int which ) const;

	QListIterator<SnapshotGene*>	getGeneIterator() const;

	bool	isVisible() const;
	void	show( bool onOff );
	void	updateVisibility( int flags );

	void	getAllTaxa( QList<SnapshotNode*> &nodes, const QString &rank = QString::null ) const;

	bool	loadFromDatabase( Bio::SqlServer &server );
	bool	loadChildrenFromDatabase( Bio::SqlServer &server, Bio::Progress *progress = NULL );
	bool	loadGenes( SnapshotGeneCollection *collection, Bio::SqlServer &server, Bio::Progress *progress = NULL );

	void	updateGeneCoverage( int numGenes, int &numLeafs, float &coverage );

private:

	int		m_taxId, m_genCodeId, m_mitoGenCodeId;
	bool	m_isVisible;
	float	m_coverage;
	QString	m_scientificName, m_commonName, m_rank;

	SnapshotNode*			m_parent;
	QList<SnapshotNode*>	m_children;
	QList<SnapshotGene*>	m_genes;
};

class SnapshotTree : public QObject{
	Q_OBJECT
public:
	
	enum VisFlags { 
		ShowAll = 0x00,
		HideEmptyNodes = 0x01,
		HideUnclassified = 0x02,
		HideEnvSamples = 0x04
	};
	
	SnapshotTree();
	virtual ~SnapshotTree();

	int				getNumRoots() const;
	int				getNumSpecies() const;
	int				indexOf( SnapshotNode *root ) const;
	SnapshotNode*	getRoot( int which ) const;

	QListIterator<SnapshotNode*>	getRootIterator() const;

	QList<SnapshotNode*>	getAllTaxa( const QString &rank = QString::null ) const;

	bool	addFromDatabase( int rootTaxonId, Bio::SqlServer &server, SnapshotGeneCollection *collection );
	void	updateGeneCoverage( int numGenes );

	void	clear();

	bool	getIgnoreEmpty() const;
	void	setIgnoreEmpty( bool onOff );

	bool	getIgnoreUnclassified() const;
	void	setIgnoreUnclassified( bool onOff );

	bool	getIgnoreEnvSamp() const;
	void	setIgnoreEnvSamp( bool onOff );

signals:

	void	rootAdded( SnapshotNode *root );
	void	cleared();
	void	coverageChanged();
	void	visibilityChanged();

private:

	void	updateVisibility();

	int						m_visFlags;
	QList<SnapshotNode*>	m_roots;
};

#endif // TAXON_UPDATE_TREE_H